<template>
  <div id="map"></div>
</template>

<script setup lang="ts">
import { onMounted, ref } from 'vue';
import chinaJson from '../assets/china.json';
import jxsJson from '../assets/jxs.json';
import * as THREE from 'three';
import {
  CSS2DRenderer,
  CSS2DObject,
} from 'three/examples/jsm/renderers/CSS2DRenderer.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import * as d3 from 'd3';
import { Reflector } from 'three/examples/jsm/objects/Reflector.js';
import {
  CSS3DRenderer,
  CSS3DObject,
} from 'three/examples/jsm/renderers/CSS3DRenderer.js';
import localTexture1 from '../assets/digitalGround1.png?url';
import localTexture2 from '../assets/digitalGround2.png?url';
import localTexture3 from '../assets/digitalGround3.png?url';
import localTexture4 from '../assets/digitalGround4.png?url';
import imgFloor1Texture from '../assets/imgFloor1.png?url';
import imgFloor2Texture from '../assets/imgFloor2.png?url';
import imgFloor3Texture from '../assets/imgFloor3.png?url';
import shotTextrue from '../assets/shot.png?url';
import { Pane } from 'tweakpane';
let map, renderer, scene, camera, controls, labelRenderer, label3DRenderer;
let imgFloor1, imgFloor2, imgFloor3;
let zooming = true; // 控制是否进行运镜动画
let zoomDuration = 4000; // 动画持续时间（毫秒）
let zoomStartTime = null;
let projection;
let mapDome;
let guangdai;
let initialZoomDone = false; // 新增变量
// 飞线坐标
let feixianArray = [];
const offsetXY = d3.geoMercator();
const circleYs = [];
const moveSpots = [];

onMounted(() => {
  // 以南昌市为中心
  projection = d3
    .geoMercator()
    .center([115.910978, 28.680175])
    .translate([0, 0]);
  createScene();
  createCamera();
  createLight();
  createFoold();
  makeMesh();
  createJXMapAopu();
  createRotateBase();
  createRanderrer();
  // createAxis();
  createControls();
  createGeometry();
  initGUI();
  animate();
  changMouseMove();
});

const changMouseMove = () => {
  let isDragging = false;
  let previousMousePosition = {
    x: 0,
    y: 0,
  };

  let sceneRotationZ = 0;

  renderer.domElement.addEventListener('pointerdown', (event) => {
    isDragging = true;
    previousMousePosition = {
      x: event.clientX,
      y: event.clientY,
    };
  });

  renderer.domElement.addEventListener('pointermove', (event) => {
    if (isDragging) {
      const deltaX = event.clientX - previousMousePosition.x;

      // 根据鼠标移动距离调整旋转角度
      const rotationSpeed = 0.01; // 控制旋转速度
      sceneRotationZ += deltaX * rotationSpeed;

      // 设置场景整体绕 Z 轴旋转
      scene.rotation.z = sceneRotationZ;

      previousMousePosition = {
        x: event.clientX,
        y: event.clientY,
      };
    }
  });

  renderer.domElement.addEventListener('pointerup', () => {
    isDragging = false;
  });
};

const initGUI = () => {
  const pane = new Pane({
    title: '地图控制',
    expanded: true,
    container: document.getElementById('gui'),
  });
  const params = {
    color1: '#350941', // <-- 对应你的 color1 颜色
    colorTop: '#8cfefe',
    textX: 0.0,
    textY: 0.0,
    textZ: 0.0,
    rotateZ: 0.0,
  };
  pane
    .addBinding(params, 'color1', { label: '侧边颜色' })
    .on('change', (ev) => {
      scene.traverse((child) => {
        if (child.isMesh && child.material && child.material.uniforms?.color1) {
          child.material.uniforms.color1.value.set(ev.value);
        }
      });
    });
  pane
    .addBinding(params, 'colorTop', { label: '顶部颜色' })
    .on('change', (ev) => {
      scene.traverse((child) => {
        if (
          child.isMesh &&
          child.material &&
          child.material.uniforms?.colorTop
        ) {
          child.material.uniforms.colorTop.value.set(ev.value);
        }
      });
    });

  // 控制光柱上方文本的位置 和 大小
  pane
    .addBinding(params, 'textX', {
      label: 'X轴位置',
      min: 0,
      max: 10,
      step: 0.01,
    })
    .on('change', (ev) => {
      scene.traverse((child) => {
        if (child.textLabelTop) {
          child.textLabelTop.position.x = ev.value;
        }
      });
    });

  pane
    .addBinding(params, 'textY', {
      label: 'Y轴位置',
      min: 0,
      max: 10,
      step: 0.01,
    })
    .on('change', (ev) => {
      scene.traverse((child) => {
        if (child.textLabelTop) {
          child.textLabelTop.position.y = ev.value;
        }
      });
    });

  pane
    .addBinding(params, 'textZ', {
      label: 'Z轴位置',
      min: 0,
      max: 10,
      step: 0.01,
    })
    .on('change', (ev) => {
      scene.traverse((child) => {
        if (child.textLabelTop) {
          child.textLabelTop.position.z = ev.value;
        }
      });
    });

  pane
    .addBinding(params, 'rotateZ', {
      label: 'Z轴旋转角度',
      min: 0,
      max: 360,
      step: 0.01,
    })
    .on('change', (ev) => {
      scene.traverse((child) => {
        if (child.textLabelTop) {
          child.textLabelTop.rotation.z = ev.value * (Math.PI / 180);
        }
      });
    });
};

// 创建动态底座
const createFoold = async () => {
  let dynamicBase;

  const textureUrls = [
    localTexture1,
    localTexture2,
    localTexture3,
    localTexture4,
  ];

  const pTexture = await Promise.all(
    textureUrls.map((url) => new THREE.TextureLoader().loadAsync(url))
  );
  pTexture.forEach((texture) => {
    texture.colorSpace = THREE.LinearSRGBColorSpace;
    texture.wrapS = THREE.RepeatWrapping;
    texture.wrapT = THREE.RepeatWrapping;
    texture.magFilter = THREE.LinearFilter;
    texture.minFilter = THREE.LinearMipmapLinearFilter;
  });

  // 设置 uniforms
  const tsmConfig = {
    uniforms: {
      time: { value: 0 },
      radius: { value: 500 }, // 可以根据需要调整大小
      uColor: { value: new THREE.Color('#de62f2') },
      texture0: { value: pTexture[0] },
      texture1: { value: pTexture[1] },
      texture2: { value: pTexture[2] },
      texture3: { value: pTexture[3] },
    },
    vertexShader: `
      varying vec3 vPosition;
      varying vec2 vUv;
      void main(){
        vPosition = position;
        vUv = uv;
        gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
      }
    `,
    fragmentShader: `
      uniform float time;
      uniform float radius;

      uniform sampler2D texture0;
      uniform sampler2D texture1;
      uniform sampler2D texture2;
      uniform sampler2D texture3;

      varying vec3 vPosition;
      uniform vec3 uColor;
      varying vec2 vUv;

      float wave(float a, float l, float s, float second, float val) {
          float PI = 3.141592653;
          float wave = a * sin(-val * 2.0 * PI / l + second * s  * 2.0 * PI / l);
          return (wave + 1.0) / 2.0;
      }

      void main(){
          vec4 basceColor = vec4(uColor, 1.0);
          vec4 back = texture2D( texture0, vUv * 16.0);

          vec4 ori1 = texture2D( texture1, vUv * 4.0); // 电子元件
          vec4 ori2 = texture2D( texture2, vUv * 16.0 ); // 点
          vec4 ori3 = texture2D( texture3, vUv * 16.0 ); // 网格

          float length = length( vec2(vPosition.x, vPosition.y) );
          // 应用波函数蒙版
          float flag1 = wave(1.0, radius / 2.0, 45.0, time, length);
          if (flag1 < 0.5) {
              flag1 = 0.0;
          }
          ori1.a = ori1.a * (flag1 * 0.8 + 0.2);
          float flag2 = wave(1.0, radius / 3.0, 30.0, time, length);
          ori2.a = ori2.a * (flag2 * 0.8 + 0.2);
          float flag3 = wave(1.0, 60.0, 20.0, time, length);
          ori3.a = ori3.a * (flag3 * 2.0 - 1.5);
          // 应用蒙版
          float alpha = clamp(ori1.a + ori2.a + ori3.a + back.a * 0.01, 0.0, 1.0);
          basceColor.a = alpha*2.0;

          gl_FragColor = basceColor * clamp((2.0 - (length * 2.0 / radius)), 0.0, 1.0);
      }
    `,
    side: THREE.DoubleSide,
    transparent: true,
  };

  dynamicBase = createDynamicBase(tsmConfig);
  scene.add(dynamicBase);
};

// 创建动态旋转底座
const createRotateBase = async () => {
  const textureLoader = new THREE.TextureLoader();
  textureLoader.load(imgFloor1Texture, (texture) => {
    const geometry = new THREE.PlaneGeometry(30, 30);
    const material = new THREE.MeshBasicMaterial({
      map: texture,
      transparent: true,
      opacity: 1,
      depthWrite: true, // 可选：图标始终显示在最前
      side: THREE.DoubleSide, // 双面渲染
    });
    imgFloor1 = new THREE.Mesh(geometry, material);
    imgFloor1.position.set(0, -3.5, 3);
    imgFloor1.userData = { clickable: true, name: '标注图标' };
    scene.add(imgFloor1);
  });

  textureLoader.load(imgFloor2Texture, (texture) => {
    const geometry = new THREE.PlaneGeometry(30, 30);
    const material = new THREE.MeshBasicMaterial({
      map: texture,
      transparent: true,
      opacity: 1,
      depthWrite: true, // 可选：图标始终显示在最前
      side: THREE.DoubleSide, // 双面渲染
    });
    imgFloor2 = new THREE.Mesh(geometry, material);
    imgFloor2.position.set(0, -3.5, 3);
    imgFloor2.userData = { clickable: true, name: '标注图标' };
    scene.add(imgFloor2);
  });

  textureLoader.load(imgFloor3Texture, (texture) => {
    const geometry = new THREE.PlaneGeometry(32, 32);
    const material = new THREE.MeshBasicMaterial({
      map: texture,
      transparent: true,
      opacity: 1,
      depthWrite: true, // 可选：图标始终显示在最前
      side: THREE.DoubleSide, // 双面渲染
    });
    imgFloor3 = new THREE.Mesh(geometry, material);
    imgFloor3.userData = { clickable: true, name: '标注图标' };
    // scene.add(imgFloor3);
  });
};

// 创建一个平面
function createDynamicBase(tsmConfig, radius = 300, segments = 64) {
  const geometry = new THREE.CircleGeometry(radius, segments);
  // 使用 tsmConfig 中定义的着色器材质
  const material = new THREE.ShaderMaterial(tsmConfig);
  const base = new THREE.Mesh(geometry, material);
  base.position.set(0, 0, 0); // 重置位置
  return base;
}

// 创建一个镜面
const createGeometry = () => {
  const mirrorGeometry = new THREE.PlaneGeometry(10000, 10000); // 调整尺寸以覆盖地图范围
  const mirror = new Reflector(mirrorGeometry, {
    color: new THREE.Color(0x8899aa),
    textureWidth: window.innerWidth * window.devicePixelRatio,
    textureHeight: window.innerHeight * window.devicePixelRatio,
    clipBias: 0.3,
    recursion: 0, // 支持递归反射（如果需要多重反射）
  });

  mirror.position.y = -0.5; // 略低于地图表面
  scene.add(mirror);
};

const createScene = () => {
  scene = new THREE.Scene();
  label3DRenderer = new CSS3DRenderer();
  labelRenderer = new CSS2DRenderer();
};

const createCamera = () => {
  camera = new THREE.PerspectiveCamera(
    10,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  camera.position.set(0, -600, 300);
};

const createJXMapAopu = async () => {
  // const url = 'https://geo.datav.aliyun.com/areas_v3/bound/360000_full.json';
  // const data = (await fetch(url).then((res) => res.json())) || jxsJson;
  const map = new THREE.Object3D();
  // 遍历地图数据的区域
  jxsJson.features.forEach((freature) => {
    const unit = new THREE.Object3D();
    // 获取区域的几何信息 和 属性
    const { centroid, center, name } = freature.properties;
    const { coordinates, type } = freature.geometry;
    const point = centroid || center || [0, 0];
    // 为每个区域 随即创建颜色
    const color = new THREE.Color('#1b3755');
    // 地图的厚度
    const depth = 3;
    // 创建标签
    // const label = createLabel(name, point, depth);
    if (!name || name === '') return;

    const ripple = createRippleEffect(point, depth);
    if (name == '南昌市' || name == '赣州市') {
      unit.add(ripple);
      // 控制光柱的高度
      addLightPillarToRipple(ripple, name);
      feixianArray.push(point);
    }

    // 创建图标
    const icon = createIcon(point, depth);
    // 根据多边形类型 构建几何体
    coordinates.forEach((coordinate) => {
      if (type === 'MultiPolygon') coordinate.forEach((item) => fn(item));
      if (type === 'Polygon') fn(coordinate);
      function fn(coordinate) {
        unit.name = name;
        const mesh = makeJXTextureAopu(coordinate, color, depth);
        const line = createLine(coordinate, depth, '#ffffff');
        unit.add(mesh, ...line);
        unit.position.set(0, 0, 3);
      }
    });
    map.add(unit);
    scene.add(map);
  });

  const line = lineConnect(
    projection(feixianArray[0]),
    projection(feixianArray[1])
  );

  scene.add(line);

  window.addEventListener('pointerdown', (event) => {
    const mouse = new THREE.Vector2();
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

    const raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(mouse, camera);

    const intersects = raycaster
      .intersectObjects(map.children)
      .filter((item) => item.object.type !== 'Line');

    if (intersects.length > 0) {
      const clickedObject = intersects[0].object;

      if (clickedObject.isMesh) {
        const region = clickedObject.parent;
        console.log('你点击的区域:', region.name);

        // 清除其他高亮
        scene.traverse((child) => {
          if (child.isMesh && child.material.uniforms?.colorTop) {
            child.material.uniforms.colorTop.value.set('#9fcde8');
          }
        });

        // 设置当前点击对象颜色
        if (clickedObject.material.uniforms?.colorTop) {
          clickedObject.material.uniforms.colorTop.value.set('#36cfcf'); // 红色高亮
        }
      }
    }
  });
};

/**
 * 两点链接飞线
 * */
function lineConnect(posStart, posEnd) {
  // 根据目标坐标设置3D坐标  z轴位置在地图表面
  const [x0, y0, z0] = [...posStart, 6];
  const [x1, y1, z1] = [...posEnd, 6];

  // 使用QuadraticBezierCurve3() 创建 三维二次贝塞尔曲线
  const curve = new THREE.QuadraticBezierCurve3(
    new THREE.Vector3(x0, -y0, z0),
    new THREE.Vector3((x0 + x1) / 2, -(y0 + y1) / 2, 20),
    new THREE.Vector3(x1, -y1, z1)
  );

  // 绘制 目标位置
  spotCircle([x1, y1, z1]);
  moveSpot(curve);

  const lineGeometry = new THREE.BufferGeometry();
  // 获取曲线 上的50个点
  var points = curve.getPoints(50);
  var positions = [];
  var colors = [];
  var color = new THREE.Color();

  // 给每个顶点设置演示 实现渐变
  for (var j = 0; j < points.length; j++) {
    color.setHSL(0.81666 + j, 0.88, 0.715 + j * 0.0025); // 粉色
    colors.push(color.r, color.g, color.b);
    positions.push(points[j].x, points[j].y, points[j].z);
  }
  // 放入顶点 和 设置顶点颜色
  lineGeometry.setAttribute(
    'position',
    new THREE.BufferAttribute(new Float32Array(positions), 3, true)
  );
  lineGeometry.setAttribute(
    'color',
    new THREE.BufferAttribute(new Float32Array(colors), 3, true)
  );

  const material = new THREE.LineBasicMaterial({
    vertexColors: THREE.VertexColors,
    side: THREE.DoubleSide,
  });
  const line = new THREE.Line(lineGeometry, material);

  return line;
}

function spotCircle(spot) {
  // 圆
  const geometry1 = new THREE.CircleGeometry(0.5, 200);
  const material1 = new THREE.MeshBasicMaterial({
    color: 0xff0000,
    side: THREE.DoubleSide,
  });
  const circle = new THREE.Mesh(geometry1, material1);
  // 绘制地图时 y轴取反 这里同步
  circle.position.set(spot[0], -spot[1], spot[2] + 0.1);

  // scene.add(circle);

  // 圆环
  const geometry2 = new THREE.RingGeometry(0.5, 0.7, 50);
  // transparent 设置 true 开启透明
  const material2 = new THREE.MeshBasicMaterial({
    color: 0xff0000,
    side: THREE.DoubleSide,
    transparent: true,
  });
  const circleY = new THREE.Mesh(geometry2, material2);
  // 绘制地图时 y轴取反 这里同步
  circleY.position.set(spot[0], -spot[1], spot[2] + 0.1);
  // scene.add(circleY);

  circleYs.push(circleY);
}

function moveSpot(curve) {
  const pillar = createLightPillar();
  pillar.curve = curve;
  pillar._s = 0;

  // 添加到场景中
  scene.add(pillar);

  // 添加动画更新逻辑
  animatePillar(pillar);
}

function createLightPillar() {
  const geometry = new THREE.BoxGeometry(0.2, 0.05, 0.22); // 宽、高、深
  const material = new THREE.MeshBasicMaterial({
    color: 0x00ffff, // 青色
    emissive: 0x00ffff, // 自发光青色
    emissiveIntensity: 1, // 发光强度
    transparent: true,
    opacity: 0.8,
  });
  const rectangle = new THREE.Mesh(geometry, material);
  rectangle.position.set(0, 0, 0.05); // 稍微抬高一点避免被地面遮挡
  rectangle.rotation.x = -Math.PI / 2; // 使矩形面向上（默认是竖直方向）

  return rectangle;
}
function animatePillar(pillar) {
  requestAnimationFrame(() => animatePillar(pillar));

  if (!pillar.curve) return;

  pillar._s += 0.01; // 控制移动速度
  if (pillar._s > 1) pillar._s = 0;

  const point = pillar.curve.getPoint(pillar._s);
  pillar.position.copy(point);

  // 实现高度脉冲效果
  const pulse = Math.sin(pillar._s * Math.PI * 2) * 0.5 + 1;
  pillar.scale.y = pulse * 0.5 + 0.5; // 缩放动画
  pillar.material.opacity =
    0.5 + Math.abs(Math.sin(pillar._s * Math.PI * 4)) * 0.5; // 透明度闪烁
}

const makeJXTextureAopu = (data, color, depth) => {
  const shape = new THREE.Shape();
  data.forEach((item, idx) => {
    const [x, y] = projection(item);
    if (idx === 0) shape.moveTo(x, -y);
    else shape.lineTo(x, -y);
  });
  const extrudeSettings = {
    depth: depth,
    bevelEnabled: false,
  };
  const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
  // 着色器 编辑材质
  const material = new THREE.ShaderMaterial({
    transparent: true,
    opacity: 1,
    wireframe: false,
    side: THREE.DoubleSide,
    blending: THREE.NormalBlending,
    uniforms: {
      colorTop: { value: new THREE.Color('#9fcde8') },
      opacity: { value: 0.9 }, // 设置你想要的透明度
      colorBottom: { value: new THREE.Color('#9fcde8') },
      time: { value: 2 },
      num: { value: 2.2 },
      speed: { value: 0.8 },
      waveIntensity: { value: 0.7 },
      // 侧边的颜色
      color1: { value: new THREE.Color('#78a8a5') },
    },
    vertexShader: /* glsl */ `
    varying vec2 vUv;
    varying vec3 vNormal;
    uniform float time;
    
    void main() {
      vNormal = normalMatrix * normal;
      vUv = uv;
      vec3 displacedPosition = position;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }
  `,
    fragmentShader: /* glsl */ `
    precision highp float;
    varying vec3 vNormal;
    varying vec2 vUv;
    uniform vec3 colorTop;
    uniform float speed;
    uniform float num;
    uniform vec3 colorBottom;
    uniform float time;
    uniform vec3 color1;
    uniform float waveIntensity;
    uniform float opacity;
    
    void main() {
      vec3 normal = normalize(vNormal);
      if(normal.y > 0.9) {
        gl_FragColor = vec4(colorTop, 0.7); // 顶部
      } else if (normal.y < -0.9) {
        gl_FragColor = vec4(colorBottom, 0.7); // 底部
      } else {
        // 侧面效果保持不变
        float alpha =fract((vUv.y + time * speed) * num );
        float fadeFactor = smoothstep(9.0, 0.1, abs(vUv.y) ); 
        alpha *= fadeFactor;
        vec3 mixedColor = mix(colorTop, color1, waveIntensity * alpha);
        gl_FragColor = vec4(mixedColor, opacity);
      }
    }
  `,
  });
  const mesh = new THREE.Mesh(geometry, material);

  return mesh;
};

// 创建着色器材质 - 替换原 createMesh 中的 material 部分
const createShaderMaterial = (baseColor: THREE.Color) => {
  return new THREE.MeshBasicMaterial({
    uniforms: {
      color: { value: baseColor }, // 基础色
      colorTop: { value: new THREE.Color('#132940') }, // 顶部颜色
      colorSide: { value: new THREE.Color('#4fc1ff') }, // 侧面颜色
      colorBottom: { value: new THREE.Color('#132940') }, // 底部颜色
    },
    vertexShader: `
      varying vec3 vNormal;
      void main() {
        vNormal = normalize(normalMatrix * normal); // 将法线转换到视图空间
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
      }
    `,
    fragmentShader: `
      varying vec3 vNormal;
      uniform vec3 color;
      uniform vec3 colorTop;
      uniform vec3 colorSide;
      uniform vec3 colorBottom;
      
      void main() {
        vec3 normal = normalize(vNormal);
        // 根据法线方向决定颜色
        if (normal.y > 0.7) {
          gl_FragColor = vec4(colorTop, 1.0);    // 顶部
        } else if (normal.y < -0.7) {
          gl_FragColor = vec4(colorBottom, 1.0); // 底部
        } else {
          gl_FragColor = vec4(colorSide, 1.0);   // 侧面
        }
      }
    `,
    side: THREE.DoubleSide,
  });
};

const makeMesh = async () => {
  // const url = 'https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json';
  // const data = (await fetch(url).then((res) => res.json())) || chinaJson;
  const map = new THREE.Object3D();
  // 遍历地图数据的区域
  chinaJson.features.forEach((freature) => {
    const unit = new THREE.Object3D();
    // 获取区域的几何信息 和 属性
    const { centroid, center, name } = freature.properties;
    const { coordinates, type } = freature.geometry;
    // 为每个区域 随即创建颜色
    const color = new THREE.Color('#1b3755');
    // 地图的厚度
    let depth = 1.5;
    // 创建标签
    if (!name || name === '') return;
    // 创建图标
    // 根据多边形类型 构建几何体
    coordinates.forEach((coordinate) => {
      if (type === 'MultiPolygon') coordinate.forEach((item) => fn(item));
      if (type === 'Polygon') fn(coordinate);

      function fn(coordinate) {
        unit.name = name;
        const mesh = createMesh(coordinate, color, depth);
        const line = createLine(coordinate, depth);
        unit.add(mesh, ...line);
      }
    });
    map.add(unit);
    scene.add(map);
  });
};

const createLight = () => {
  const mainLight = new THREE.DirectionalLight(0xffffff, 0.9);
  mainLight.position.set(0, 100, 100);
  scene.add(mainLight);
  // 辅助光源 - 从左侧打来
  const sideLight = new THREE.DirectionalLight(0xffffff, 0.5);
  sideLight.position.set(-100, 50, 0);
  scene.add(sideLight);

  // 环境光 - 均匀提升整体亮度
  const ambientLight = new THREE.AmbientLight(0xffffff, 0.3); // soft white light
  // scene.add(ambientLight);

  // 添加主光源辅助器
  const mainHelper = new THREE.DirectionalLightHelper(mainLight, 25);
  // scene.add(mainHelper);

  // 添加辅助光源辅助器（可选）
  const sideHelper = new THREE.DirectionalLightHelper(sideLight, 20);
  // scene.add(sideHelper);
  // 添加灯光-灯光辅助器
  const light = new THREE.DirectionalLight(0xffffff, 0.9);
  light.position.set(0, 100, 100); // 正面打光
  scene.add(light);
  const helper = new THREE.DirectionalLightHelper(light, 25);
  // scene.add(helper);
};

const createRanderrer = () => {
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);

  // 添加 CSS2DRenderer 的 DOM 元素
  labelRenderer.setSize(window.innerWidth, window.innerHeight);
  labelRenderer.domElement.style.position = 'absolute';
  labelRenderer.domElement.style.top = '0px';
  labelRenderer.domElement.style.left = '0px';
  labelRenderer.domElement.style.pointerEvents = 'none'; // 避免遮挡交互
  document.body.appendChild(labelRenderer.domElement);

  // 初始化 CSS3DRenderer
  label3DRenderer = new CSS3DRenderer();
  label3DRenderer.setSize(window.innerWidth, window.innerHeight);
  label3DRenderer.domElement.style.position = 'absolute';
  label3DRenderer.domElement.style.top = '0px';
  label3DRenderer.domElement.style.left = '0px';
  label3DRenderer.domElement.style.pointerEvents = 'none';
  document.body.appendChild(label3DRenderer.domElement);
};

const createControls = () => {
  controls = new OrbitControls(camera, renderer.domElement);
  controls.mouseButtons = {
    LEFT: THREE.MOUSE.ROTATE,
    MIDDLE: THREE.MOUSE.DOLLY,
    RIGHT: THREE.MOUSE.PAN,
  };
  controls.enableZoom = true; // 启用缩放
  controls.enableRotate = false; // 启用旋转
  controls.enablePan = false; // 禁用平移
  controls.enableDamping = true;
  controls.dampingFactor = 0.09; // 阻尼系数
  controls.rotateSpeed = 0.5; // 旋转速度
};

const animate = () => {
  requestAnimationFrame(animate);
  const jiangxiCenter = [0, 0];
  controls.target.set(jiangxiCenter[0], -jiangxiCenter[1], 0);

  const time = performance.now() * 0.005; // 控制速度

  if (!initialZoomDone) {
    const targetPosition = new THREE.Vector3(0, -200, 70); // 目标位置
    const duration = 3000; // 持续时间 (ms)
    const ease = 0.05; // 插值系数

    // 平滑插值到目标位置
    camera.position.lerp(targetPosition, ease);
 // 绕 Y 轴缓慢旋转（每帧旋转一定角度）
  const rotateSpeed = 0.002; // 控制旋转速度（弧度/帧）
  camera.position.applyAxisAngle(new THREE.Vector3(0, 1, 0), rotateSpeed);
    // 判断是否已经接近目标位置
    if (camera.position.distanceTo(targetPosition) < 1) {
      camera.position.copy(targetPosition);
      initialZoomDone = true;
    }

    camera.lookAt(0, 0, 0); // 始终看向地图中心
  }
  

  scene.traverse((child) => {
    if (child.isCSS3DObject && child.isBillboard) {
      child.lookAt(camera.position); // 面向相机
    }

    if (
      child.isMesh &&
      child.userData.targetHeight !== undefined &&
      child.userData.growing
    ) {
      const now = performance.now();
      const delay = 1000; // 动画持续时间（毫秒）

      if (now >= child.userData.startGrowTime) {
        const elapsed = now - child.userData.startGrowTime;
        const t = Math.min(elapsed / delay, 1); // 归一化时间 [0 ~ 1]

        const currentHeight = child.userData.targetHeight * t;

        // 更新几何体（或使用 scale 更高效）
        child.scale.y = currentHeight / 0.1; // Cylinder 默认高度是 0.1
        child.position.z = currentHeight / 2; // 保持底部不动，调整中心位置
        if (t >= 1) {
          child.userData.growing = false; // 动画完成
        }
      }
    }

    if (
      child.isMesh &&
      child.material.uniforms &&
      child.material.uniforms.time
    ) {
      child.material.uniforms.time.value = time;
    }

    // 新增：查找带有涟漪材质的 mesh 并更新
    if (
      child.material instanceof THREE.ShaderMaterial &&
      child.material.uniforms.time
    ) {
      child.material.uniforms.time.value = time;
    }

    if (
      child.material &&
      child.material.uniforms &&
      child.material.uniforms.time
    ) {
      child.material.uniforms.time.value = performance.now() * 0.001;
    }
  });

  scene.traverse((obj) => {
    if (obj.isCSS3DObject && obj.isBillboard) {
      obj.lookAt(camera.position); // 面向相机
    }
  });

  controls.update();
  if (imgFloor1 && imgFloor1?.rotation) {
    imgFloor1.rotation.z += 0.01;
  }
  if (imgFloor2 && imgFloor2?.rotation) {
    imgFloor2.rotation.z += 0.01;
  }

  // imgFloor3.rotation.z += 0.01;
  labelRenderer.render(scene, camera);
  label3DRenderer.render(scene, camera); // 渲染 3D 标签
  renderer.render(scene, camera);
};

// 工具类
// 创建坐标轴
const createAxis = () => {
  const axesHelper = new THREE.AxesHelper(1000);
  scene.add(axesHelper);
};

// 添加光柱
const addLightPillarToRipple = (
  rippleGroup,
  name,
  height = Math.round(Math.random() * 10),
  radius = 0.1
) => {
  const textureLoader = new THREE.TextureLoader();
  textureLoader.load(shotTextrue, (texture) => {
    const geometry = new THREE.CylinderGeometry(radius, radius, 0.1, 32); // 初始高度设为 0.1
    const material = new THREE.MeshBasicMaterial({
      // map: texture,
      color: '#ffffff',
      transparent: true,
      alphaTest: 0.5,
      depthWrite: true, // 可选：图标始终显示在最前
      side: THREE.DoubleSide, // 双面渲染
    });
    const cylinder = new THREE.Mesh(geometry, material);
    cylinder.position.set(0, 0, 0.05); // 初始位置
    cylinder.rotation.set(Math.PI / 2, 0, 0);
    // 自定义属性，记录目标高度和开始增长时间（单位：ms）
    cylinder.userData = {
      targetHeight: height,
      startGrowTime: performance.now() + 1000, // 延迟 1 秒
      growing: true,
    };
    rippleGroup.add(cylinder);
    // 在光柱顶部添加文本 发光
    createTextTop(name, rippleGroup, height);
    const text = createTextTop(name, rippleGroup, height);
    rippleGroup.add(text);
  });
};

const createTextTop = (name, rippleGroup, height) => {
  const textDiv = document.createElement('div');
  textDiv.style.color = '#00FFFF'; // 发光颜色
  textDiv.style.fontSize = '14px';
  textDiv.style.fontWeight = 'bold';
  textDiv.style.textShadow = '0 0 5px #00FFFF'; // 发光效果
  textDiv.textContent = name; // 使用传入的名称

  const label = new CSS3DObject(textDiv);
  label.position.set(0, 0, height + 0.1); // 设置在光柱顶部
  label.scale.set(0.05, 0.05, 0.05); // 调整缩放以匹配场景
  label.isBillboard = true;
  rippleGroup.textLabelTop = label;
  return label;
};

const createRippleEffect = (point, depth) => {
  const innerRadius = 0.1; // 内半径
  const outerRadius = 0.7; // 外半径
  const thetaSegments = 32;

  const geometry = new THREE.RingGeometry(
    innerRadius,
    outerRadius,
    thetaSegments
  );

  const material = new THREE.ShaderMaterial({
    uniforms: {
      time: { value: 0 },
      color: { value: new THREE.Color(0x00eaff) }, // 光圈主色
      opacity: { value: 1 },
    },
    vertexShader: /* glsl */ `
      varying vec2 vUv;
      void main() {
        vUv = uv;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
      }
    `,
    fragmentShader: /* glsl */ `
      precision highp float;
      uniform float time;
      uniform vec3 color;
      uniform float opacity;
      varying vec2 vUv;
      

      void main() {
        vec2 center = vec2(0.5);
        float dist = distance(vUv, center);

        float wave1 = sin(dist * 20.0 - time * 5.0);
        float wave2 = sin(dist * 15.0 - time * 3.0);
        float wave = (wave1 + wave2) * 0.5;

        float alpha = smoothstep(0.7, 0.0, dist) * (wave * 0.5 + 0.5) * opacity;

        vec3 colorA = vec3(0.0, 0.9, 1.0);
        vec3 colorB = vec3(0.0, 1.0, 0.5);
        vec3 waveColor = mix(colorA, colorB, wave * 0.5 + 0.5);

        gl_FragColor = vec4(waveColor, alpha);
}
    `,
    transparent: true,
    blending: THREE.AdditiveBlending,
    side: THREE.DoubleSide,
  });

  const ripple = new THREE.Mesh(geometry, material);

  // 设置位置
  const [x, y] = projection(point);

  ripple.position.set(x, -y, depth + 0.1); // 抬高一点避免被遮挡
  ripple.rotation.set(0, 0, Math.PI / 2);
  return ripple;
};

const createLine = (data, depth, color = '#244b75') => {
  const points = [];
  data.forEach((item) => {
    const [x, y] = projection(item);
    points.push(new THREE.Vector3(x, -y, 0));
  });
  const lineGeometry = new THREE.BufferGeometry().setFromPoints(points);
  const uplineMaterial = new THREE.LineBasicMaterial({ color: color });
  const downlineMaterial = new THREE.LineBasicMaterial({ color: color });

  const upLine = new THREE.Line(lineGeometry, uplineMaterial);
  const downLine = new THREE.Line(lineGeometry, downlineMaterial);
  downLine.position.z = -0.0001;
  upLine.position.z = depth + 0.0001;
  return [upLine, downLine];
};

const createMesh = (data, color, depth) => {
  const shape = new THREE.Shape();
  data.forEach((row, i) => {
    const [x, y] = projection(row);
    if (i === 0) {
      shape.moveTo(x, -y);
    }
    shape.lineTo(x, -y);
  });

  const extrudeSettings = {
    depth: depth,
    bevelEnabled: false,
  };
  const material = new THREE.MeshPhongMaterial({
    color: color,
    side: THREE.DoubleSide,
  });
  const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
  const mesh = new THREE.Mesh(geometry, material);

  return mesh;
};

const createLabel = (name, point, depth) => {
  const div = document.createElement('div');

  // 设置样式 - 背景 + 文字颜色 + 内边距等
  div.style.backgroundColor = 'rgba(0, 51, 102, 0.7)'; // 自定义背景色（深蓝半透明）
  div.style.color = '#ffffff'; // 白色文字
  div.style.fontSize = '14px';
  div.style.padding = '4px 8px';
  div.style.borderRadius = '4px';
  div.style.textAlign = 'center';
  div.style.textShadow = '1px 1px 2px #047cd6';

  // 添加图标（使用本地图片）
  const icon = document.createElement('img');
  icon.src = new URL('../assets/local.png', import.meta.url).href; // 使用项目中的图标
  icon.style.width = '16px';
  icon.style.height = '16px';
  icon.style.verticalAlign = 'middle';
  icon.style.marginRight = '5px';

  // 设置文本内容
  const text = document.createTextNode(name);

  // 组合图标 + 文本
  div.appendChild(icon);
  div.appendChild(text);

  // 创建 CSS2DObject
  const label = new CSS2DObject(div);
  label.scale.set(0.01, 0.01, 0.01); // 原始缩放

  // 地图坐标转换为 THREE 坐标
  const [x, y] = projection(point);
  label.position.set(x, -y, depth); // 设置位置

  return label;
};

const createIcon = (point, depth) => {
  const url = new URL('../assets/local.png', import.meta.url).href;
  const map = new THREE.TextureLoader().load(url);
  const material = new THREE.SpriteMaterial({
    map: map,
    transparent: true,
  });
  const sprite = new THREE.Sprite(material);
  const [x, y] = projection(point);
  sprite.scale.set(1, 1, 1);

  sprite.position.set(x + 0.5, -y, depth + 0.5);
  sprite.renderOrder = 1;

  return sprite;
};
</script>

<style scoped></style>
